/*******************************************************************************
 * Level Master 2000
 * Copyright (C) 2010 Christian Herzog
 * For more information see http://code.google.com/p/levelmaster2000/
 *
 * This file is licensed under the terms of the MIT license, see
 * http://www.opensource.org/licenses/mit-license.php for further information.
 ******************************************************************************/

#include "Logger.h"

#include "ui_log.h"

#include "Config.h"

#include <QToolButton>
#include <QTextStream>
#include <QFile>
#include <QDomDocument>

Logger* Logger::theInstance = 0;

Logger* Logger::instance()
{
    if( !theInstance )
    {
        theInstance = new Logger();
    }
    return theInstance;
}

void Logger::destroyInstance()
{
    delete theInstance;
    theInstance = 0;
}


//Logger::Logger( )
//        : QDockWidget( parent )
//{
//}

Logger::~Logger()
{
    destroyInstance();
}

//QDockWidget* Logger::logWidget = 0;
//QTextEdit* Logger::log = 0;

void Logger::init( QWidget *parent )
{
    logWidget = new QDockWidget( parent );
    Ui::LogWidget uiLogWidget;
    uiLogWidget.setupUi( logWidget );

    logWidget->show();
    log = logWidget->findChild<QTextEdit*>( "log" );

    QToolButton *clearButton = logWidget->findChild<QToolButton*>( "clearButton" );
    clearButton->connect( clearButton,
                          SIGNAL( clicked() ),
                          this,
                          SLOT( clearButtonClicked() ) );


    QToolButton *showInfoButton = logWidget->findChild<QToolButton*>( "showInfoButton" );
    showInfo =  showInfoButton->isChecked();
    clearButton->connect( showInfoButton,
                          SIGNAL( clicked() ),
                          this,
                          SLOT( showInfoButtonClicked() ) );

    QToolButton *showWarningButton = logWidget->findChild<QToolButton*>( "showWarningButton" );
    showWarning =  showWarningButton->isChecked();
    clearButton->connect( showWarningButton,
                          SIGNAL( clicked() ),
                          this,
                          SLOT( showWarningButtonClicked() ) );

    QToolButton *showErrorButton = logWidget->findChild<QToolButton*>( "showErrorButton" );
    showError =  showErrorButton->isChecked();
    clearButton->connect( showErrorButton,
                          SIGNAL( clicked() ),
                          this,
                          SLOT( showErrorButtonClicked() ) );

    QToolButton *showDebugButton = logWidget->findChild<QToolButton*>( "showDebugButton" );
    showDebug =  showDebugButton->isChecked();
    clearButton->connect( showDebugButton,
                          SIGNAL( clicked() ),
                          this,
                          SLOT( showDebugButtonClicked() ) );

    //addDockWidget(Qt::BottomDockWidgetArea, logWidget);


    //We need to load settings.xml, and create the two log files:
    QDomDocument settingsDoc( "settingsDoc" );
    QFile file( Config::SETTINGS_XML );

    if( !file.open( QIODevice::ReadOnly ) )
    {
        addLogMessage( Logger::LL_ERROR, "LevelMaster2000::initSettings", "Failed to load settings.xml!" );
    }

    if( !settingsDoc.setContent( &file ) )
    {
        file.close();
        addLogMessage( Logger::LL_ERROR, "LevelMaster2000::initSettings", "Could not set content of settings.xml!" );
    }

    file.close();

    QDomElement root = settingsDoc.documentElement();
    if( root.tagName() != "settings" )
    {
        addLogMessage( Logger::LL_ERROR, "LevelMaster2000::initSettings", "Root tag not of type settings!" );
    }

    //Everything is valid, now we can parse the settings file:
    QDomElement settingsNode = root.firstChildElement();

    while( !settingsNode.isNull() )
    {
        //Create the logfile:
        if( settingsNode.tagName() == "logfile" )
        {
            QFile file( settingsNode.attribute( "path" ) );
            file.open( QIODevice::WriteOnly );
            file.close();
            logfilePath = settingsNode.attribute( "path" );
        }

        //Create the command file:
        if( settingsNode.tagName() == "commandfile" )
        {
            QFile file( settingsNode.attribute( "path" ) );
            file.open( QIODevice::WriteOnly );
            file.close();
            commandfilePath = settingsNode.attribute( "path" );
        }

        settingsNode = settingsNode.nextSiblingElement();
    }
}

void Logger::clearButtonClicked()
{
    messages.clear();
    log->clear();
}

void Logger::showInfoButtonClicked()
{
    QToolButton *showInfoButton = logWidget->findChild<QToolButton*>( "showInfoButton" );
    showInfo =  showInfoButton->isChecked();
    updateLog();
}

void Logger::showWarningButtonClicked()
{
    QToolButton *showWarningButton = logWidget->findChild<QToolButton*>( "showWarningButton" );
    showWarning =  showWarningButton->isChecked();
    updateLog();
}

void Logger::showErrorButtonClicked()
{
    QToolButton *showErrorButton = logWidget->findChild<QToolButton*>( "showErrorButton" );
    showError =  showErrorButton->isChecked();
    updateLog();
}

void Logger::showDebugButtonClicked()
{
    QToolButton *showDebugButton = logWidget->findChild<QToolButton*>( "showDebugButton" );
    showDebug =  showDebugButton->isChecked();
    updateLog();
}

void Logger::updateLog()
{
     log->clear();

     foreach( LogData data, messages )
     {
         if( showInfo && data.logLevel == LL_INFO )
         {
            log->setTextColor( QColor( 0, 0, 0 ) );
            log->append( data.message );
         }

         if( showWarning && data.logLevel == LL_WARNING )
         {
            log->setTextColor( QColor( "orange" ) );
            log->append( data.message );
         }

         if( showError && data.logLevel == LL_ERROR )
         {
            log->setTextColor( QColor( "red" ) );
            log->append( data.message );
         }

         if( showDebug&& data.logLevel == LL_DEBUG )
         {
            log->setTextColor( QColor( "green" ) );
            log->append( data.message );
         }
     }
}

void Logger::addLogMessage( LOG_LEVEL level, QString loggerName, QString message )
{
    LogData data;
    data.logLevel = level;
    data.message = "[" + loggerName + "]:" + message;;

    //For sake of ease, when debug, only add the command...
    if( level == LL_DEBUG )
    {
        data.message = message;
    }

    messages.push_back( data );

    if( showInfo && data.logLevel == LL_INFO )
    {
       log->setTextColor( QColor( 0, 0, 0 ) );
       log->append( data.message );
    }

    if( showWarning && data.logLevel == LL_WARNING )
    {
       log->setTextColor( QColor( "orange" ) );
       log->append( data.message );
    }

    if( showError && data.logLevel == LL_ERROR )
    {
       log->setTextColor( QColor( "red" ) );
       log->append( data.message );
    }

    if( showDebug&& data.logLevel == LL_DEBUG )
    {
       log->setTextColor( QColor( "green" ) );
       log->append( data.message );

       //Also log to commandfile:
       QFile commandfile( commandfilePath );
       if( commandfile.open( QIODevice::Append | QIODevice::Text ) )
       {
           QTextStream commandStreamer( &commandfile );
           commandStreamer <<  data.message << "\n";
           commandfile.close();
       }
    }

    //Also log to file:
    QFile file( logfilePath );
    if( file.open( QIODevice::Append | QIODevice::Text ) )
    {
        QTextStream streamer( &file );
        streamer <<  data.message << "\n";
        file.close();
    }
}

void Logger::addLogMessage( QString level, QString loggerName, QString message )
{
    if( level == "ERROR" )
    {
        Logger::addLogMessage( Logger::LL_ERROR, loggerName, message );
    }
    else if( level == "WARNING" )
    {
        Logger::addLogMessage( Logger::LL_WARNING, loggerName, message );
    }
    else if( level == "DEBUG" )
    {
        Logger::addLogMessage( Logger::LL_DEBUG, loggerName, message );
    }
    else
    {
        Logger::addLogMessage( Logger::LL_INFO, loggerName, message );
    }
}
